package cn.wwk.notification.common.exception;

import cn.wwk.notification.common.result.CodeMsg;
import cn.wwk.notification.common.result.Result;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;

/**
 *  * 好处：可以实现对项目中所有产生的异常进行拦截，在同一个类中实现统一处理。避免异常漏处理的情况。
 *  *
 *  *
 *  * @ControllerAdvice
 *  * @ControllerAdvice是一个@Component，用于定义@ExceptionHandler，@InitBinder和@ModelAttribute方法，
 *  * 适用于所有使用@RequestMapping方法，会对所有@RequestMapping方法进行检查，拦截。并进行异常处理。
 *  *
 *  * @ExceptionHandler
 *  * 标注要被拦截的异常，value=Exception.class代表拦截所有的异常，
 *  *
 *  * @ResponseBody
 *  * 为了方便输出，使得这个GlobalExceptionHandler类里面的方法跟我们Controller类一样是输出的信息，返回值Result类型，可以携带信息。
 *  * 当参数校验不通过的时候，输出也是Result（CodeMsg）,传给前端用于前端显示获取处理。
 *
 * @author wwk
 */
@Slf4j
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

    //拦截什么异常
    @ExceptionHandler(value = Exception.class)  //拦截所有的异常
    public Result<String> exceptionHandler(HttpServletResponse response, Exception e) {
        log.error("捕获到异常" + e.getClass());
        if (e instanceof GlobalException) {
            GlobalException ex = (GlobalException) e;
            return Result.error(ex.getCm());
        } else if (e instanceof MethodArgumentNotValidException) {
            //是绑定异常的情况
            //强转
            MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
            BindingResult bindingResult = ex.getBindingResult();
            List<FieldError> fieldErrors = bindingResult.getFieldErrors();
            HashMap<String, String> errorMap = new HashMap<>();
            log.error("捕获到异常" + errorMap);
            for (FieldError fieldError : fieldErrors) {
                //验证错误的 field
                String field = fieldError.getField();
                //验证错误信息
                String defaultMessage = fieldError.getDefaultMessage();
                //存入当前错误信息到map中
                errorMap.put(field,defaultMessage);
            }
            return Result.error(CodeMsg.LOGIN_ERROR.fillMsg(JSON.toJSONString(errorMap)));
        } else {  //不是绑定异常的情况
            return Result.error(CodeMsg.SERVER_ERROR);
        }
    }

}
